package com.huijie.app.u.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlHelper;
import com.google.common.collect.Lists;
import com.huijie.app.u.entity.Role;
import com.huijie.app.u.entity.User;
import com.huijie.app.u.entity.UserRole;
import com.huijie.app.u.mapper.RoleMapper;
import com.huijie.app.u.mapper.UserMapper;
import com.huijie.app.u.mapper.UserRoleMapper;
import com.huijie.app.u.service.IUserService;
import com.huijie.app.sys.aspect.SystemServiceLog;
import com.huijie.core.common.BaseEntity;
import com.huijie.core.common.BaseServiceImpl;
import com.huijie.core.constant.BusinessConstants;
import com.huijie.core.constant.BussinessCode;
import com.huijie.core.util.BussinessMsgUtil;
import org.apache.commons.lang.StringUtils;
import org.jsets.shiro.model.Account;
import org.jsets.shiro.util.ShiroUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static com.huijie.core.constant.Constants.INIT_LOGIN_PWD;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author echen
 * @since 2019-01-09
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implements IUserService {

    private final RoleMapper roleMapper;
    private final UserRoleMapper userRoleMapper;

    @Autowired
    public UserServiceImpl(RoleMapper roleMapper, UserRoleMapper userRoleMapper) {
        this.roleMapper = roleMapper;
        this.userRoleMapper = userRoleMapper;
    }


    /**
     * @param userLoginName 用户登陆名
     * @return com.cn.rfid.model.vo.system.User
     * @description: 根据用户名获取用户信息
     * @author Alex
     * @date 2018/9/25 16:56
     */
    @Override
    public User getUserByloginName(String userLoginName) {
        LambdaQueryWrapper<User> wrapper = new QueryWrapper<User>().lambda().eq(User::getUserLoginName, userLoginName).eq(User::getUserStatus, BusinessConstants.SYS_USER_STATUS_OK.getCode());
        return baseMapper.selectOne(wrapper);
    }


    /**
     * @param userId    用户ID
     * @param userStatus 用户状态-正常、锁定、删除
     * @return com.cn.rfid.model.vo.base.BussinessMsg
     * @description: 更改用户状态
     * @author Alex
     * @date 2018/9/25 16:40
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void updateUserStatus(Integer userId, Integer userStatus) {
        log.debug("锁定用户开始，用户ID:" + userId);
        long start = System.currentTimeMillis();
        try {
            User user = new User();
            user.setId(userId);
            user.setUserStatus(userStatus);
            baseMapper.updateById(user);
            user = this.getById(userId);
            ShiroUtils.clearAuthCache(user.getUserLoginName());
        } catch (Exception e) {
            log.error("失效用户方法内部错误", e);
            throw e;
        } finally {
            log.debug("锁定用户失效,用时" + (System.currentTimeMillis() - start) + "毫秒");
        }
        BussinessMsgUtil.returnCodeMessage(BussinessCode.GLOBAL_SUCCESS);
    }

    /**
     * @param userId    用户ID
     * @return com.cn.rfid.model.vo.system.User
     * @description: 用户状态失效
     * @author Alex
     * @date 2018/9/25 13:42
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public User updateUserStatus(Integer userId) {
        log.debug("用户失效开始，当前用户Id:" + userId);
        long start = System.currentTimeMillis();
        User user;
        try {
            //解除用户与角色绑定关系
            LambdaQueryWrapper<UserRole> queryWrapper = new QueryWrapper<UserRole>().lambda().eq(UserRole::getUserId, userId);
            List<UserRole> userRoles = userRoleMapper.selectList(queryWrapper);
            if (null != userRoles && !userRoles.isEmpty()) {
                for (UserRole userRole : userRoles) {
                    userRoleMapper.deleteById(userRole.getId());
                }
            }
            //更改用户状态为1-失效
//            params.put("modifier", loginName);
            user = new User();
            user.setId(userId);
            user.setUserStatus(BusinessConstants.SYS_USER_STATUS_INVALID.getCode());
            this.updateById(user);
            user = this.getById(userId);
            ShiroUtils.clearAuthCache(user.getUserLoginName());
        } catch (Exception e) {
            log.error("失效用户方法内部错误", e);
            throw e;
        } finally {
            log.debug("用户失效结束,用时" + (System.currentTimeMillis() - start) + "毫秒");
        }
        return user;
    }

    /**
     * @param userIds   用户ID
     * @param loginName 当前登录用户名
     * @return boolean
     * @description: 批量用户状态失效  TODO 改为真正批量
     * @author Alex
     * @date 2018/9/25 14:51
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation=Propagation.REQUIRED)
    public void updateUserBatchStatus(Integer[] userIds, String loginName) {
        log.debug("批量失效用户开始，当前用户Id:" + Arrays.toString(userIds));
        long start = System.currentTimeMillis();
        try {
            if (null != userIds && userIds.length > 0) {
                for (Integer userId : userIds) {
                    //解除用户与角色绑定关系
                    updateUserStatus(userId);
                }
            }

        } catch (Exception e) {
            log.error("失效用户方法内部错误", e);
            throw e;
        } finally {
            log.debug("批量失效用户结束,用时" + (System.currentTimeMillis() - start) + "毫秒");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class,propagation=Propagation.REQUIRED)
    public void deleteUser(Integer userId){
        log.debug("删除用户信息开始,当前用户Id:" + userId);
        long start = System.currentTimeMillis();
        try {
            //删除用户与角色的关系
            userRoleMapper.deteleUserRoleByUserId(userId);
            //删除用户
            baseMapper.deleteById(userId);
        } catch (Exception e) {
            log.error("删除用户信息方法内部错误", e);
            throw e;
        } finally {
            log.debug("删除用户信息结束,用时" + (System.currentTimeMillis() - start) + "毫秒");
        }
    }

    /**
     * @param user 用户 传输实体
     * @param loginName   当前登录用户
     * @return com.cn.rfid.model.vo.system.User
     * @description: 新增用户信息
     * @author Alex
     * @date 2018/9/25 13:10
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    @SystemServiceLog(description = "新增用户信息Service")
    public User insertUser(User user, String loginName) {
        log.debug("新增用户信息开始");
        long start = System.currentTimeMillis();
        try {
            user.setUserPassword(INIT_LOGIN_PWD);
            user.setUserStatus(BusinessConstants.SYS_USER_STATUS_OK.getCode());
            this.insert(user);
        } catch (Exception e) {
            log.error("新增用户信息方法内部错误", e);
            throw e;
        } finally {
            log.debug("新增用户信息结束,用时" + (System.currentTimeMillis() - start) + "毫秒");
        }
        return user;
    }

    /**
     * @param user 用户 传输实体
     * @param loginName   当前登录用户
     * @return com.cn.rfid.model.vo.system.User
     * @description: 更新用户信息
     * @author Alex
     * @date 2018/9/25 13:23
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    @SystemServiceLog(description = "更新用户信息Service")
    public User updateUser(User user, String loginName) {
        log.debug("更新用户信息开始");
        long start = System.currentTimeMillis();
        try {
            this.updateById(user);
        } catch (Exception e) {
            log.error("更新用户信息方法内部错误", e);
            throw e;
        } finally {
            log.debug("更新用户信息结束,用时" + (System.currentTimeMillis() - start) + "毫秒");
        }
        return user;
    }

    /**
     * @param userId 用户ID
     * @return com.cn.rfid.model.vo.system.User
     * @description: 根据用户Id查询用户角色信息
     * @author Alex
     * @date 2018/9/25 17:42
     */
    @Override
    public User selectUserRolesByUserId(Integer userId) {
        if (userId != null) {
            //单个User的实体
            User user = baseMapper.selectById(userId);
            //用户所对应的角色信息
            List<Role> roles = roleMapper.selectRolesByUserId(userId);
            getAccountRole(roles, user);
            return user;
        }
        return null;
    }

    /**
     * @param userId     用户id
     * @param roleIds    分配的角色信息
     * @param longinName 当前登录用户名称
     * @return boolean
     * @description: 新增用户分配角色信息
     * @author Alex
     * @date 2018/9/25 15:55
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void saveUserRole(Integer userId, String roleIds, String longinName) {
        log.debug("新增用户分配角色信息开始");
        long start = System.currentTimeMillis();
        try {
            LambdaQueryWrapper<UserRole> queryWrapper = new QueryWrapper<UserRole>().lambda().eq(UserRole::getUserId, userId);
            List<UserRole> userRoles = userRoleMapper.selectList(queryWrapper);
            //如果角色Id不为空插入用户角色信息，否则删除用户下所有分配的角色
            if (StringUtils.isNotEmpty(roleIds)) {
                if (null != userRoles && !userRoles.isEmpty()) {
                    for (UserRole userRole : userRoles) {
                        userRoleMapper.deleteById(userRole.getId());
                    }
                }
                for (String roleId : roleIds.split(",")) {
                    UserRole ur = new UserRole();
                    ur.setUserId(userId);
                    ur.setRoleId(Integer.valueOf(roleId));
                    userRoleMapper.insert(ur);
                }

            } else {
                if (null != userRoles && !userRoles.isEmpty()) {
                    for (UserRole userRole : userRoles) {
                        userRoleMapper.deleteById(userRole.getId());
                    }
                    ShiroUtils.clearAuthCache(baseMapper.selectById(userId).getUserLoginName());
                }
            }
        } catch (Exception e) {
            log.error("新增用户分配角色信息方法内部错误", e);
            throw e;
        } finally {
            log.debug("新增用户分配角色信息结束,用时" + (System.currentTimeMillis() - start) + "毫秒");
        }
    }

    /**
     * @param userLoginName 登录名
     * @param userPassword 密码
     * @return boolean
     * @description: 验证密码
     * @author Alex
     * @date 2018/9/25 16:23
     */
    @Override
    public boolean validate(String userLoginName,String userPassword) {
        return !StringUtils.isEmpty(userPassword) && userPassword.equals(
                baseMapper.selectPasswordByloginName(userLoginName));
    }

    /**
     * @param userLoginName 登录名
     * @param userPassword 密码
     * @return boolean
     * @description: 修改用户密码
     * @author Alex
     * @date 2018/9/25 17:05
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    @SystemServiceLog(description = "保存用户密码Service")
    public void modifyUserPasswordByUserLoginName(String userLoginName,String userPassword) {
        log.debug("保存用户密码开始");
        long start = System.currentTimeMillis();
        try {
            LambdaUpdateWrapper<User> updateWrapper = new UpdateWrapper<User>().lambda().set(User::getPassword, userPassword).eq(User::getUserLoginName, userLoginName);
            baseMapper.update(null,updateWrapper);
        } catch (Exception e) {
            log.error("用户修改密码错误", e);
        } finally {
            log.debug("保存用户密码结束,用时" + (System.currentTimeMillis() - start) + "毫秒");
        }
    }
    /**
     * @param userIds   用户ID
     * @return boolean
     * @description: 批量用户删除
     * @author Alex
     * @date 2018/9/25 14:51
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation=Propagation.REQUIRED)
    public Integer batchDeleteUser(Integer[] userIds) {
        log.debug("批量删除用户开始，当前用户Id:" + Arrays.toString(userIds));
        long start = System.currentTimeMillis();
        Integer delCount = 0;
        try {
            if (null != userIds && userIds.length > 0) {
                List<Integer> userRoleIdList = new ArrayList<Integer>();
                for (Integer userId : userIds) {
                    //解除用户与角色绑定关系
                    LambdaQueryWrapper<UserRole> queryWrapper = new QueryWrapper<UserRole>().lambda().eq(UserRole::getUserId, userId);
                    List<UserRole> userRoles = userRoleMapper.selectList(queryWrapper);
                    if (null != userRoles && !userRoles.isEmpty()) {
                        for (UserRole userRole : userRoles) {
                            userRoleIdList.add(userRole.getUserId());
                        }
                    }
                }
                if (!userRoleIdList.isEmpty()) {
                    userRoleMapper.deleteBatchIds(userRoleIdList);
                }
                for (Integer userId : userIds) {
                    User user = baseMapper.selectById(userId);
                    if (user!=null) {
                        ShiroUtils.clearAuthCache(user.getUserLoginName());
                    }
                }
                delCount = baseMapper.deleteBatchIds(Lists.newArrayList(userIds));
            }

        } catch (Exception e) {
            log.error("批量删除用户方法内部错误", e);
            throw e;
        } finally {
            log.debug("批量删除用户结束,用时" + (System.currentTimeMillis() - start) + "毫秒");
        }
        return delCount;
    }

    @Override
    public Boolean selectUserLoginNameCheck(String userLoginName, Integer userId) {

        LambdaQueryWrapper<User> wrapper = new QueryWrapper<User>().lambda();
        if(StringUtils.isNotBlank(userLoginName)){
            wrapper.eq(User::getUserLoginName,userLoginName);
        }
        if(userId!=null){
            wrapper.ne(BaseEntity::getId,userId);
        }
        return SqlHelper.retBool(baseMapper.selectCount(wrapper));
    }

    /**
     * @param roles   角色数组
     * @param account 账号实体
     * @return void
     * @description: TODO
     * @author Alex
     * @date 2018/9/26 18:35
     */
    void getAccountRole(List<Role> roles, Account account) {
        StringBuilder sb = new StringBuilder();
        StringBuilder sb2 = new StringBuilder();
        if (null != roles && !roles.isEmpty()) {
            for (Role role : roles) {
                sb.append(role.getId()).append(",");
                sb2.append(role.getRoleName()).append(",");
            }
            if (sb.length() > 0) {
                sb.deleteCharAt(sb.length() - 1);
                account.setRoleIds(sb.toString());
            }
            if (sb2.length() > 0) {
                sb2.deleteCharAt(sb2.length() - 1);
                account.setRoleNames(sb2.toString());
            }
        }
    }

}
